<script setup lang="ts">
import {reactive, ref, watchEffect} from "vue";
import SparkMD5 from 'spark-md5';
import { checkMd5, merge, upload } from '@/api/fileupload.ts';
const props = defineProps(['content'])
const content=ref()
watchEffect(()=>{
  const contentReal = props.content
  if (contentReal){
    content.value = contentReal
  }
})
const mavonEditorRef = ref()
const baseUrl = import.meta.env.VITE_API_URL
const imgs = ref([])

const state = reactive({
  file: null as File | null,
  md5: '',
  uploadProgress: 0
});

interface fileBlob {
  start: number,
  end: number,
  index: number,
  hash: string,
  blob: Blob
}

const uploadRef = ref();
const MD5Status = ref(false);
const CHUNK_SIZE = 1024 * 1024 * 5; // 最少5M,minio合并最低要求
const THREAD_COUNT = navigator.hardwareConcurrency || 4;
const chunks = ref<fileBlob[]>([]);
const imgAdd =async (pos:any,$file:any)=>{
  MD5Status.value = true;
  let md5;
  const file = $file
  await cutFile(file).then((res: any) => {
    chunks.value = res;
    const md5Values = res.map((it: any) => it.hash).join('');
    md5 = SparkMD5.hash(md5Values);
    MD5Status.value = false;
  });
  uploadFileBtn(pos,md5,file)

  /*const formData = new FormData();
  formData.append("file",$file);
  imgs.value[pos]=$file
  upload(formData).then((data:any)=>{
    let url = data.data
    console.log(url);
    mavonEditorRef.value.$img2Url(pos,url.substring(0,url.indexOf('?')).replace('http://124.221.209.30:19000/','https://img.springautumncome.asia/'));
  })*/
}
const loading=ref(false)
const uploadFileBtn = async (pos,md5,file) => {
  if (!file) return;
  loading.value=true
  let uploadProgress = 0;


  // 先询问后端哪些chunk已经上传过
  let uploadedChunks = new Set();
  await checkMd5(md5).then((response: any) => {
    uploadedChunks = new Set(response.msg.split(':').map(Number));
  });


  for (let i = 0; i < chunks.value.length; i++) {
    // 不包含片段
    if (!uploadedChunks.has(i + 1)) {
      await uploadChunk(chunks.value[i].blob, i + 1, md5);
    }
    uploadProgress = Math.floor(((i + 1) / chunks.value.length) * 100);
    if (uploadProgress === 100) {
      // uploadRef.value.clearFiles();
    }
  }
  const formData = new FormData();
  formData.append('fileName', file.name);
  formData.append('md5', md5);
  // 通知后端进行合并
  await merge(formData).then(url => {
    if (url.code == 200){
      let imgUrl = url.data.substring(0,url.data.indexOf('?'))
      console.log('文件url', imgUrl);
      imgUrl = imgUrl.replace('http://124.221.209.30:19000/','https://img.springautumncome.asia/')
      console.log('文件url', imgUrl);
      mavonEditorRef.value.$img2Url(pos,imgUrl);
      emit('complete',true)
    }
  });
  loading.value=false
};

const uploadChunk = async (chunk: Blob, chunkNumber: number, md5: string) => {
  const formData = new FormData();
  formData.append('chunk', chunk);
  formData.append('chunkNumber', chunkNumber.toString());
  formData.append('md5', md5);

  await upload(formData);
};


async function cutFile(file: File) {
  return new Promise((resolve, reject) => {
    const chunks = Math.ceil(file.size / CHUNK_SIZE);
    const threadChunkCount = Math.ceil(chunks / THREAD_COUNT);
    const result: any[] = [];
    let finishCount = 0;

    for (let i = 0; i < THREAD_COUNT; i++) {
      // 分配线程任务
      const worker = new Worker(new URL('@/utils/minio.ts', import.meta.url), {
        type: 'module'
      });
      const start = i * threadChunkCount;
      let end = (i + 1) * threadChunkCount;
      if (end > chunks) {
        end = chunks;
      }
      worker.postMessage({
        file,
        start,
        end,
        CHUNK_SIZE
      });
      worker.onmessage = e => {
        try {
          result[i] = e.data;
          worker.terminate();
          finishCount++;
          if (finishCount === THREAD_COUNT) {
            resolve(result.flat());
          }
        } catch (error) {
          reject(`Error processing the file in worker: ${error}`);
        }
      };
      worker.onerror = (error) => {
        reject(`Worker encountered an error: ${error}`);
      };
    }
  });
}
const imgDel=(pos)=>{
  // imgs.value.pop(pos)
  delete imgs.value[pos]
}
const emit=defineEmits(['contentData','complete'])
const editdata=()=>{
  var obj = {content:mavonEditorRef.value,contentHtml:mavonEditorRef.value.d_render}
  emit('contentData',obj)
}
</script>

<template>
  <mavon-editor class="editor" ref="mavonEditorRef" v-model="content"  :ishljs="true"
                @imgAdd="imgAdd" @imgDel="imgDel" @change="editdata" v-loading="loading"/>
</template>

<style scoped>
.editor{
  height:60vh;
  width:100%;
}
</style>